<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Tools;

use Exception;

class Aes
{
    private const BLOCK_SIZE                = 32;               // PKCS7块大小
    private const AES_KEY_SIZE              = 32;               // KEY字符串长度
    private const IV_KEY_SIZE               = 16;               // IV字符串长度
    private const AES_256_CBC               = 'AES-256-CBC';    // AES-256-CBC
    
    /**
     * @param string $text
     * @return string
     * 编码补位待加密字符内容
     */
    public static function pkcs7Encode(string $text):string
    {
        $enString       = '';
        $textLength     = strlen($text);
        if($textLength < 1) return $enString;
        $toPadLength    = self::BLOCK_SIZE - ($textLength % self::BLOCK_SIZE);
        if($toPadLength < 1) $toPadLength = self::BLOCK_SIZE;
        return $text.implode('', array_fill(0, $toPadLength, chr($toPadLength)));
    }
    
    /**
     * @param string $text
     * @return string
     * 解码移除补位的字符串
     */
    public static function pkcs7Decode(string $text):string
    {
        $deString       = '';
        $textLength     = strlen($text);
        if($textLength < 1) return $deString;
        $padCharInt     = ord(substr($text, -1));
        if($padCharInt < 1 || $padCharInt > self::BLOCK_SIZE){
            $deString   = $text;
        }else{
            $deString   = substr($text, 0, $textLength - $padCharInt);
        }
        return $deString;
    }

    /**
     * @param string $text
     * @param string $aesKey
     * @param string $ivKey
     * @param bool $result
     * @return string
     * AES-256-CBC加密
     */
    public static function encrypt(string $text, string $aesKey, string $ivKey = '', bool &$result = false):string
    {
        if(strlen($text) < 1 || strlen($aesKey) < 1) return '';
        if(strlen($ivKey) < 1) $ivKey = $aesKey;
        try{
            $encrypt                = openssl_encrypt($text, self::AES_256_CBC, substr($aesKey, 0, self::AES_KEY_SIZE) , 0, substr($ivKey, 0, self::IV_KEY_SIZE));
            if(is_string($encrypt) && strlen($encrypt) > 0){
                $result             = true;
                return $encrypt;
            }else{
                $result             = false;
                return '';
            }
        }catch(Exception $Exception){
        }
        $result                     = false;
        return '';
    }

    /**
     * @param string $encrypt
     * @param string $aesKey
     * @param string $ivKey
     * @param bool $result
     * @return string
     * AES-256-CBC解密
     */
    public static function decrypt(string $encrypt, string $aesKey, string $ivKey = '', bool &$result = false):string
    {
        if(strlen($encrypt) < 1 || strlen($aesKey) < 1) return '';
        if(strlen($ivKey) < 1) $ivKey = $aesKey;
        try{
            $decrypt                = openssl_decrypt($encrypt, self::AES_256_CBC, substr($aesKey, 0, self::AES_KEY_SIZE) , 0, substr($ivKey, 0, self::IV_KEY_SIZE));
            if(is_string($decrypt) && strlen($decrypt) > 0){
                $result             = true;
                return $decrypt;
            }else{
                $result             = false;
                return '';
            }
        }catch(Exception $Exception){
        }
        $result                     = false;
        return '';
    }

    /**
     * @param string $text
     * @param string $aesKey
     * @param string $ivKey
     * @param bool $result
     * @return string
     * AES-256-CBC加密(ForPkcs7)
     */
    public static function encryptForPkcs7(string $text, string $aesKey, string $ivKey = '', bool &$result = false):string
    {
        if(strlen($text) < 1 || strlen($aesKey) < 1) return '';
        if(strlen($ivKey) < 1) $ivKey = $aesKey;
        try{
            $text                   = self::pkcs7Encode($text);
            $encrypt                = openssl_encrypt($text, self::AES_256_CBC, substr($aesKey, 0, self::AES_KEY_SIZE) , OPENSSL_ZERO_PADDING, substr($ivKey, 0, self::IV_KEY_SIZE));
            if(is_string($encrypt) && strlen($encrypt) > 0){
                $result             = true;
                return $encrypt;
            }else{
                $result             = false;
                return '';
            }
        }catch(Exception $Exception){
        }
        $result                     = false;
        return '';
    }

    /**
     * @param string $encrypt
     * @param string $aesKey
     * @param string $ivKey
     * @param bool $result
     * @return string
     * AES-256-CBC解密(ForPkcs7)
     */
    public static function decryptForPkcs7(string $encrypt, string $aesKey, string $ivKey = '', bool &$result = false):string
    {
        if(strlen($encrypt) < 1 || strlen($aesKey) < 1) return '';
        if(strlen($ivKey) < 1) $ivKey = $aesKey;
        try{
            $decrypt                = openssl_decrypt($encrypt, self::AES_256_CBC, substr($aesKey, 0, self::AES_KEY_SIZE) , OPENSSL_ZERO_PADDING, substr($ivKey, 0, self::IV_KEY_SIZE));
            if(is_string($decrypt) && strlen($decrypt) > 0){
                $result             = true;
                return self::pkcs7Decode($decrypt);
            }else{
                $result             = false;
                return '';
            }
        }catch(Exception $Exception){
        }
        $result                     = false;
        return '';
    }
}